package com.lollipop.checkin.service.impl;

import com.lollipop.checkin.constant.CheckInConstant;
import com.lollipop.checkin.dto.CheckInRequest;
import com.lollipop.checkin.dto.CheckInResponse;
import com.lollipop.checkin.service.CheckInService;
import com.lollipop.redis.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 签到服务实现类
 * 实现签到相关的业务逻辑
 */
@Service
public class CheckInServiceImpl implements CheckInService {

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 用户签到
     *
     * @param request 签到请求
     * @return 签到响应
     */
    @Override
    public CheckInResponse checkIn(CheckInRequest request) {
        // 验证请求参数
        if (request == null || request.getUserId() == null) {
            return CheckInResponse.failed("用户ID不能为空");
        }

        String userId = request.getUserId();
        String checkInDate = request.getCheckInDate();
        String activityId = request.getActivityId();

        // 如果没有指定签到日期，则使用当前日期
        if (checkInDate == null || checkInDate.isEmpty()) {
            SimpleDateFormat sdf = new SimpleDateFormat(CheckInConstant.DATE_FORMAT);
            checkInDate = sdf.format(new Date());
        } else {
            // 验证日期格式
            SimpleDateFormat sdf = new SimpleDateFormat(CheckInConstant.DATE_FORMAT);
            sdf.setLenient(false);
            try {
                sdf.parse(checkInDate);
            } catch (ParseException e) {
                return CheckInResponse.failed("日期格式不正确，请使用yyyy-MM-dd格式");
            }
        }

        // 构建Redis键
        String checkInRecordKey = String.format(CheckInConstant.USER_CHECKIN_RECORD_KEY_PREFIX, userId);
        String continueDaysKey = String.format(CheckInConstant.USER_CONTINUE_CHECKIN_DAYS_KEY_PREFIX, userId);
        String totalDaysKey = String.format(CheckInConstant.USER_TOTAL_CHECKIN_DAYS_KEY_PREFIX, userId);

        // 检查是否已经签到
        boolean alreadyCheckedIn = redisUtils.sIsMember(checkInRecordKey, checkInDate);
        if (alreadyCheckedIn) {
            return CheckInResponse.alreadyCheckedIn(checkInDate);
        }

        // 进行签到
        redisUtils.sAdd(checkInRecordKey, checkInDate);

        // 设置签到记录的过期时间（1年）
        redisUtils.expire(checkInRecordKey, 365, TimeUnit.DAYS);

        // 获取前一天的日期
        String yesterday = getYesterday(checkInDate);

        // 检查是否连续签到
        int continueDays = 1;
        if (redisUtils.sIsMember(checkInRecordKey, yesterday)) {
            // 如果前一天已经签到，则连续签到天数+1
            Object lastContinueDaysObj = redisUtils.get(continueDaysKey);
            if (lastContinueDaysObj != null) {
                continueDays = Integer.parseInt(lastContinueDaysObj.toString()) + 1;
            }
        } else {
            // 如果前一天未签到，则重置连续签到天数为1
            continueDays = 1;
        }

        // 更新连续签到天数
        redisUtils.set(continueDaysKey, continueDays);
        redisUtils.expire(continueDaysKey, 365, TimeUnit.DAYS);

        // 更新总签到天数
        int totalDays = 1;
        Object lastTotalDaysObj = redisUtils.get(totalDaysKey);
        if (lastTotalDaysObj != null) {
            totalDays = Integer.parseInt(lastTotalDaysObj.toString()) + 1;
        }
        redisUtils.set(totalDaysKey, totalDays);
        redisUtils.expire(totalDaysKey, 365, TimeUnit.DAYS);

        // 检查是否为首次签到
        boolean firstCheckIn = totalDays == 1;

        // 如果有活动，则记录用户参与活动的签到
        long activityParticipants = 0;
        if (activityId != null) {
            String activityCheckInUsersKey = String.format(CheckInConstant.ACTIVITY_CHECKIN_USERS_KEY_PREFIX, activityId);
            redisUtils.sAdd(activityCheckInUsersKey, userId.toString());
            redisUtils.expire(activityCheckInUsersKey, 365, TimeUnit.DAYS);
            activityParticipants = redisUtils.sMembers(activityCheckInUsersKey).size();
        }

        return CheckInResponse.success(checkInDate, continueDays, totalDays, firstCheckIn, activityParticipants);
    }

    /**
     * 获取用户签到记录
     *
     * @param userId 用户ID
     * @return 签到记录（日期列表）
     */
    @Override
    public List<String> getUserCheckInRecords(String userId) {
        if (userId == null) {
            return Collections.emptyList();
        }

        String checkInRecordKey = String.format(CheckInConstant.USER_CHECKIN_RECORD_KEY_PREFIX, userId);
        Set<Object> members = redisUtils.sMembers(checkInRecordKey);

        List<String> records = new ArrayList<>();
        for (Object member : members) {
            records.add(member.toString());
        }

        // 按日期排序
        records.sort((a, b) -> b.compareTo(a));

        return records;
    }

    /**
     * 获取用户连续签到天数
     *
     * @param userId 用户ID
     * @return 连续签到天数
     */
    @Override
    public int getUserContinueCheckInDays(String userId) {
        if (userId == null) {
            return 0;
        }

        String continueDaysKey = String.format(CheckInConstant.USER_CONTINUE_CHECKIN_DAYS_KEY_PREFIX, userId);
        Object value = redisUtils.get(continueDaysKey);

        return value == null ? 0 : Integer.parseInt(value.toString());
    }

    /**
     * 获取用户总签到天数
     *
     * @param userId 用户ID
     * @return 总签到天数
     */
    @Override
    public int getUserTotalCheckInDays(String userId) {
        if (userId == null) {
            return 0;
        }

        String totalDaysKey = String.format(CheckInConstant.USER_TOTAL_CHECKIN_DAYS_KEY_PREFIX, userId);
        Object value = redisUtils.get(totalDaysKey);

        return value == null ? 0 : Integer.parseInt(value.toString());
    }

    /**
     * 获取活动签到人数
     *
     * @param activityId 活动ID
     * @return 签到人数
     */
    @Override
    public long getActivityCheckInUsersCount(String activityId) {
        if (activityId == null) {
            return 0;
        }

        String activityCheckInUsersKey = String.format(CheckInConstant.ACTIVITY_CHECKIN_USERS_KEY_PREFIX, activityId);
        Set<Object> members = redisUtils.sMembers(activityCheckInUsersKey);

        return members == null ? 0 : members.size();
    }

    /**
     * 重置用户签到数据
     * （仅用于测试和特殊情况）
     *
     * @param userId 用户ID
     * @return 是否重置成功
     */
    @Override
    public boolean resetUserCheckInData(String userId) {
        if (userId == null) {
            return false;
        }

        String checkInRecordKey = String.format(CheckInConstant.USER_CHECKIN_RECORD_KEY_PREFIX, userId);
        String continueDaysKey = String.format(CheckInConstant.USER_CONTINUE_CHECKIN_DAYS_KEY_PREFIX, userId);
        String totalDaysKey = String.format(CheckInConstant.USER_TOTAL_CHECKIN_DAYS_KEY_PREFIX, userId);

        redisUtils.delete(checkInRecordKey);
        redisUtils.delete(continueDaysKey);
        redisUtils.delete(totalDaysKey);

        return true;
    }

    /**
     * 获取前一天的日期
     *
     * @param dateStr 当前日期（格式：yyyy-MM-dd）
     * @return 前一天的日期（格式：yyyy-MM-dd）
     */
    private String getYesterday(String dateStr) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(CheckInConstant.DATE_FORMAT);
            Date date = sdf.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            return sdf.format(calendar.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
            return dateStr;
        }
    }
}